#include "system/includes.h"
#include "btstack/btstack_task.h"
#include "app_config.h"
#include "app_action.h"
#include "gpadc.h"
#include "app_tone.h"
#include "gpio_config.h"
#include "app_main.h"
#include "asm/charge.h"
#include "update.h"
#include "app_power_manage.h"
#include "audio_config.h"
#include "app_charge.h"
#include "bt_profile_cfg.h"
#include "update_loader_download.h"
#include "idle.h"
#include "bt_tws.h"
#include "key_driver.h"
#include "adkey.h"
#include "user_cfg.h"
#include "usb/device/usb_stack.h"
#include "usb/usb_task.h"
#include "dev_manager.h"
#include "vm.h"
#include "iokey.h"
#include "asm/lp_touch_key_api.h"
#include "fs/sdfile.h"
#include "utils/syscfg_id.h"
#include "asm/power/power_reset.h"
#include "app_default_msg_handler.h"
#include "earphone.h"
#include "usb/otg.h"
#include "skey/skey.h"

#include "debug.h"
#define LOG_TAG "[EXT_MIC]"

#define EXT_MIC_FUNC_ID TWS_FUNC_ID('E','M','I','C')
/**
 * @brief 
 * @param  port_info        My Param doc
 * @return int              1: pulled out, 0: inserted 
 * @author zhengziyang (zhengziyang@zh-jieli.com)
 */
static int mic_insert_check(void *port_info)
{
    u32 ret =adc_get_value((enum AD_CH)port_info);
    ret = adc_value_to_voltage_filter(ret);
    // logln_info("%d",ret);
    if(ret > 4)
    {
        ret = 1;
    }
    else
    {
        ret = 0;
    } 
    return ret;
}

int ExtMicDetector_init(void *args)
{
    enum AD_CH ad = (enum AD_CH)args;
    u32 inital_value;
    adc_add_sample_ch(ad);
    adc_set_sample_period(ad, 500);
    adc_io_ch_set(ad, PORT_INPUT_PULLUP_10K);
    inital_value = adc_get_value(ad);
    inital_value = adc_value_to_voltage_filter(inital_value);
    log_pos("ExtMicDetectorStatus:%u\n",inital_value);

    return 0;
}

#define TWS_FUNC_EXT_MIC_STATE_MASK BIT(0)
#define TWS_FUNC_NEED_HANDLE_MASK BIT(2)
u8 is_ext_mic_inserted = false;
void ext_mic_callback(void *this, keyTriggerTypeDef signal)
{
    int tws_state = tws_api_get_tws_state();
    u8 handle_tmp;
    switch (signal)
    {
    case KEY_TRIGGER_PRESSED:
        log_info("MIC inserted\n");
        handle_tmp = true;
        /* code */
        break;
    case KEY_TRIGGER_RELEASED:
        log_info("MIC pulled out\n");
        handle_tmp = false;
    break; 
    default:
        break;
    }
    is_ext_mic_inserted = handle_tmp;
    if(tws_state & TWS_STA_SIBLING_CONNECTED)
    {
        if(tws_api_get_role() == TWS_ROLE_MASTER)
        {
            handle_tmp &= ~TWS_FUNC_NEED_HANDLE_MASK;
        }
        else
        {
            handle_tmp |= TWS_FUNC_NEED_HANDLE_MASK;
        }
        int err = tws_api_send_data_to_sibling((&handle_tmp),1,EXT_MIC_FUNC_ID);
    }
}

KEY_CHECK_MEMBER_REGISTER(ExtMic) = {
    .combo_timeout = KEY_CHECK_DEFAULT_COMBO_TICK, //timeout=x * 30ms,default x=7
    .key_trigger_type =KEY_TRIGGER_PRESSED | KEY_TRIGGER_RELEASED, // ex. KEY_TRIGGER_CLICKED
    .port_info = (void*)AD_CH_IO_PC4, //set args for 'getPortValueCallback' behind 
    .getPortValueCallback = mic_insert_check, // return int: 1(high) or 0(low)
    .portInitCallback = ExtMicDetector_init,// init port,NULL if don't need
    .trigger_callback = ext_mic_callback, // callback when trigger,param:(void *p:this_member,keyTriggerTypeDef signal:trigger type) 
};

static void tws_ext_mic_handle_in_task(u8 *ext_mic_state)
{
    logln_info("%u",*ext_mic_state);
    is_ext_mic_inserted = (*ext_mic_state) & TWS_FUNC_EXT_MIC_STATE_MASK;
    if(((*ext_mic_state) & TWS_FUNC_NEED_HANDLE_MASK) == 0)
    {
        return;
    }
    if(tws_api_get_role() == TWS_ROLE_MASTER){
        if(is_ext_mic_inserted)
        {
            tws_api_auto_role_switch_disable(); // 关闭自动角色切换。
            tws_api_role_switch(); //从机易位
        }
        else{
            tws_api_auto_role_switch_enable();
        }
    }
    free(ext_mic_state);
}

static void tws_ext_mic_callback(u8 *data, u8 len)
{
    int msg[4];

    u8 *buf = malloc(len);
    if (!buf) {
        return;
    }
    memcpy(buf, data, len);

    msg[0] = (int)tws_ext_mic_handle_in_task;
    msg[1] = 1;
    msg[2] = (int)buf;

    os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
}

static void tws_ext_mic_handler(void *_data, u16 len, bool rx)
{
    u8 *data = (u8 *)_data;

    if (!rx) {
        return;
    }
    tws_ext_mic_callback(data, len);
}
REGISTER_TWS_FUNC_STUB(tws_a2dp_player_stub) = {
    .func_id = EXT_MIC_FUNC_ID,
    .func = tws_ext_mic_handler,
};